﻿using GN.Pay.TradeChannel.AliPay.Response;
using GN.Pay.Utils;
using GN.Pay.Utils.Net.Http;
using GN.Pay.Utils.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace GN.Pay.TradeChannel.AliPay.Request
{
    /// <summary>
    /// 退款请求
    /// </summary>
    [Serializable]
    class RefundRequest : AServiceRequest
    {
        private RefundRequest()
        {

        }

        /// <summary>
        /// 获取服务
        /// </summary>
        public override string Service
        {
            get
            {
                return "refund_fastpay_by_platform_nopwd";
            }
        }

        /// <summary>
        /// 服务器异步 通知页面路径 支付宝服务器主动通知商户 网站里指定的页面http路径。
        /// </summary>
        public string Notify_Url { get; set; }

        /// <summary>
        /// 退款批次号,不可空 
        /// <para>每进行一次即时到账批量退款，都需要提供一个批次号，</para>
        /// <para>通过该批次号可以查询这一 批次的退款交易记录。</para>
        /// <para>对于 每一个合作伙伴，传递的每 一个批次号都必须保证唯一 性。 </para>
        /// <para>格式为：退款日期（8 位当天 日期）+流水号（3～24 位， 流水号可以接受数字或英文字符，建议使用数字，</para>
        /// <para>但不 可接受“000”）。 </para>
        /// </summary>
        public string Batch_No { get; set; }

        /// <summary>
        /// 退款请求时间
        /// <para>退款请求的当前时间。 格式为：yyyy-MM-dd hh:mm:ss。 </para>     
        /// </summary>
        public string Refund_Date { get; set; }

        /// <summary>
        /// 退款总笔数,必须大于零
        ///  <para>即参数 detail_data 的值中， “#”字符出现的数量加 1， 最大支持 1000 笔（即“#” 字符出现的最大数量 999 个）。  </para>   
        /// </summary>
        public int Batch_Num { get; set; }

        /// <summary>
        /// 单笔数据集
        /// </summary>
        public string Detail_Data { get; set; }

        /// <summary>
        /// 申请结果返 回类型 
        /// </summary>
        public string Return_Type
        {
            get
            {
                return "xml";
            }
        }

        private static string DetailData(string tradeNo, decimal refundMoney, string refounReson)
        {
            refounReson = "协商退款";
            return string.Format("{0}^{1}^{2}", tradeNo, Math.Round(refundMoney, 2).ToString(), refounReson);
        }

        /// <summary>
        /// 创建请求
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="order"></param>
        /// <param name="config"></param>
        /// <returns></returns>
        public static RefundRequest CreateRequest(ITradeChannel channel,
            IRefundApplyInfo apply,
            AliPayConfigure config)
        {
            if (apply == null)
            {
                channel.ThrowChannelValidationException("请求的 apply 为 null");
            }
            if (string.IsNullOrWhiteSpace(apply.TradeNo))
            {
                channel.ThrowChannelValidationException("请求的原支付宝交易号不能为空。");
            }
            RefundRequest request = new RefundRequest()
            {
                Batch_No = apply.RefundNo,
                Batch_Num = 1,
                Notify_Url = config.RefundNotifyUrl,
                Partner = config.ConfigureInfo.AccountId,
                Refund_Date = apply.ApplyTime.ToString("yyyy-MM-dd HH:mm:ss"),
                Sign_Type = "RSA",
                _Input_Charset = config.Encoding.WebName,
                Detail_Data = DetailData(apply.TradeNo, apply.ApplyMoney, apply.RefundReason)
            };
            return request;
        }

        /// <summary>
        /// 生成
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="config"></param>
        /// <param name="apply"></param>
        /// <returns></returns>
        public RefundResponse Build(ITradeChannel channel,
            AliPayConfigure config, IRefundApplyInfo apply)
        {
            var param = this.BuildSignDictionary(channel, config, "Sign", "Sign_Type");
            param = param.Clone(k =>
                {
                    return k.ToLower();
                }, v =>
                {
                    return HttpUtility.UrlEncode(v, config.Encoding);
                });            
            string url = config.GateWayUrl + "?_input_charset=" + config.Encoding.WebName;
            string responseString = HttpUtils.PostString(url, param, config.Encoding);
            return new RefundResponse(responseString, channel, config, apply);
        }
    }
}
